//
// Created by qianchen on 2020/12/15.
//

#ifndef TEST_CASCADE_CASCADEINFATRYDETECTER_H
#define TEST_CASCADE_CASCADEINFATRYDETECTER_H

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

class CascadeInfatryDetecter
{
public:
    /**
     * @brief ctor.输入cascade_path路径
     * @param cascade_path
     */
    CascadeInfatryDetecter(string & cascade_path);
    CascadeInfatryDetecter(string &&cascade_path);
    /**
     * @brief 加载infantry_cascade分类器
     * @return
     */
    bool Init();
    /**
     * @brief 在frame中检测步兵
     * @param frame
     * @param prior_point 装甲板中心点充当先验信息
     * @param vis 是否可视化
     * @return
     */
    bool detect(Mat &frame, Rect prior_rec, bool vis=false);


protected:
    /**
     * @brief 利用先验矩形获取位置合适的ROI，减少计算量,dx,dy传回
     * @param frame
     * @param prior_rec
     * @param ROI
     * @param dx
     * @param dy
     */
    void getROIwithRect(Mat frame, Rect prior_rec, Mat & ROI, int & dx, int & dy);

    /**
     * @brief 可视化。将objects画出来，并且标注得分
     * @param frame 需要被画的那个玩意
     * @param justOne true：只画出theCorrectRect false：画出所有objects
     */
    void drawResult(Mat & frame,bool justOne=true)
    {
        if (justOne)
        {
            if (isSafe(frame,theCorrectRect))
                rectangle(frame,theCorrectRect,Scalar(155, 110, 0),2);
        } else
        {
            for ( size_t i = 0; i < objects.size(); i++ )
            {
                //if(scores[i]>0)//负的有的还是挺准的，不过没有包括整个车
                {
                    rectangle(frame,objects[i],Scalar(155, 110, 0),2);
                    putText(frame, to_string(scores[i]), objects[i].tl(), 0, 1.0, Scalar(0, 255, 0));
                }

            }
        }
        cv::imshow( "debug", frame );
//        waitKey(1);
    }

    /**
     * @brief 判断small是否在big内部
     * @param rect1
     * @param rect2
     * @return
     */
    bool isInside(Rect & big, Rect & small)
    {
        return (big == (big&small));
    }

    bool isSafe(Mat & frame, Rect & maybeSafeRec)
    {
        if(theCorrectRect.empty()
            ||theCorrectRect.x<0
            ||theCorrectRect.y<0
            ||theCorrectRect.x+theCorrectRect.width>frame.cols
            ||theCorrectRect.y+theCorrectRect.height>frame.rows)
            return false;
        else
            return true;
    }


private:
    //!级联分类器路径
    string path;
    //!级联分类器
    CascadeClassifier infantry_cascade;
    //!存放目标框
    vector<Rect> objects;
    //!存放得分
    vector<double> scores;
    //!存放最有可能的那个（包含装甲板且最大，emmm，最大意味着不太会出错吧）
    Rect theCorrectRect;
};


#endif //TEST_CASCADE_CASCADEINFATRYDETECTER_H
